<?php
/*
 * CRMDbParams File
 *
 * @link http://riedel-st.de
 * @author Stefan Riedel <sr@riedel-st.de>
*/

/**
 * Description of CRMDbParams
 *
 * @author Stefan Riedel
 *
 */
class CRMDbConfig extends CAttributeCollection implements IApplicationComponent {
	
	protected $_initialized = false;
	
	protected $_db;
	
	/**
	 * the db connection id
	 * @var string
	 */
	public $connectionId;
	
	/**
	 * loading module configuration from database?
	 * @var bool
	 */
	public $modulesConfig = false;
	
	/**
	 * loading components configuration from database
	 * @var bool
	 */
	public $componentsConfig = false;
	/**
	 * autoloading the configuration
	 * if false we will use lazy loading
	 * @var bool
	 */
	public $autoload = false;
	
	/**
	 * Initializes the application component.
	 * This method is invoked after the application completes configuration.
	 */
	public function init() {
		if ($this->autoload) {
			$this->_initAutoloadingConfigs ();
		}
		/**
		 * @todo if autoload is false set global application config by lazy loading too.
		 */
		$this->_initialized = true;
	}
	/**
	 * @return boolean whether the {@link init()} method has been invoked.
	 */
	public function getIsInitialized() {
		return $this->_initialized;
	}
	
	public function getDbConnection() {
		if ($this->_db instanceof CDbConnection) {
			return $this->_db;
		} elseif (($id = $this->connectionId) !== null) {
			if (($this->_db = Yii::app ()->getComponent ( $id )) instanceof CDbConnection) {
				return $this->_db;
			} else {
				throw new CException ( 'Die Datenbankverbindung scheint nicht korrekt zu sein.' );
			}
		} else {
			throw new CException ( 'Bitte definiere eine DB Connection Id. Z.B. array(\'connectionId\'=>\'db\')' );
		}
	}
	
	public function importModel() {
		/**
		 * @todo models which will use on vendor libs move in an own folder in vendor lib dir
		 */
		return Yii::import ( 'application.models.Options' );
	}
	
	protected function _initAutoloadingConfigs() {
		$this->importModel ();
		$options = new Options ();
		$config = $options->findAll ( 'options_autoload=:autoload', array (':autoload' => 1 ) );
		if ($config) {
			$app = Yii::app ();
			$components = array ();
			foreach ( $config as $conf ) {
				$value = $conf->options_value;
				if(!empty($conf->options_import_file)) {
					try {
						Yii::import($conf->options_import_file);	
					} catch(CException $e) {
						throw new CException(Yii::t('crm', '{file} existiert leider nicht!', array('{file}' => $conf->options_import_file)));
					}
				}
				if (method_exists ( $app, ($setterMethod = 'set' . ucfirst ( $conf->options_name )) ) && ( int ) $conf->options_type === 0) {
					/**
					 * for this option exist a setter method
					 */
					$app->{$setterMethod} ( $value );
				} elseif (property_exists ( $app, $conf->options_name )) {
					/**
					 * for this option exist a public property
					 */
					$app->{$conf->options_name} = $value;
				} elseif (( int ) $conf->options_type === 1 && $this->componentsConfig) {
					/**
					 * we can now add own components in the database
					 * this is good for flexibility
					 * @global array $GLOBALS['components']
					 * @name $components
					 */
					$components [$conf->options_name] = $value;
				} else {
					throw new CException ( 'Can\'t set ' . $conf->options_name );
				}
			}
			if ($this->componentsConfig && ! empty ( $components )) {
				$app->setComponents ( $components );
			}
		}
	}
	
	public function __set($name, $value) {
		try {
			$param = $this->_fetchParam ( $name );
			if ($param) {
				$param->options_value = $value;
				$param->save ();
			}
			$this->add ( $name, $value );
		} catch ( CException $e ) {
			parent::__set ( $name, $value );
		}
	}
	
	protected function _fetchParam($name) {
		$this->importModel ();
		$options = new Options ();
		$res = $options->find ( 'options_name=:name', array (':name' => $name ) );
		return $res;
	}
	
	public function __get($name) {
		if ($this->contains ( $name )) {
			return $this->itemAt ( $name );
		}
		try {
			return $this->_loadParam ( $name );
		} catch ( CException $e ) {
			return parent::__get ( $name );
		}
	}
	
	protected function _loadParam($name) {
		$res = $this->_fetchParam ( $name );
		if ($res) {
			$this->add ( $name, $res->options_value );
			return $res->options_value;
		}
		throw new CException ( 'Can\'t load ' . $name . '.' );
	}
}
?>
